package cn.lkk.samples.lang.reflection;

import javax.lang.model.element.TypeElement;
import java.lang.reflect.*;
import java.sql.ParameterMetaData;
import java.util.Scanner;

/**
 * 演示如何打印一个类型定义。包含了以下类的基本使用方式
 * 1. Class：包含了类的信息
 * 2. Field：封装了对象的字段信息
 * 3. Method：封装了对象的方法的信息
 * 4. Constructor：封装了对象的构造方法的信息
 */
public class ReflectionTest {
    public static void main(String[] args) throws ClassNotFoundException {
        String className = "";
        Scanner in = new Scanner(System.in);
        System.out.print("Enter a class name:");
        className = in.next();
        Class clazz = Class.forName(className);

        //打印类声明
        int mod = clazz.getModifiers();
        String modStr = Modifier.toString(mod);
        if (modStr != null && modStr.length() > 0)
            System.out.print(modStr + " ");
        System.out.print(clazz.getName());
        //打印父类声明
        Class superClazz = clazz.getSuperclass();
        if (superClazz != Object.class) {
            System.out.print(" extends " + superClazz.getName());
        }

        System.out.println("\n{");

        printFields(clazz);
        System.out.println();

        printConstructor(clazz);
        System.out.println();

        printMethods(clazz);
        System.out.println();

        System.out.println("}");

    }

    //打印字段信息
    public static void printFields(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //打印缩进
            System.out.print("\t");

            //打印修饰符
            int mod = field.getModifiers();
            String modStr = Modifier.toString(mod);
            if (modStr != null && modStr.length() > 0)
                System.out.print(modStr + " ");

            //打印字段类型与字段名
            Class type = field.getType();
            System.out.println(type.getName() + " " + field.getName() + ";");
        }
    }

    //打印方法信息
    public static void printMethods(Class clazz) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            //打印缩进
            System.out.print("\t");

            //打印修饰符
            int mod = method.getModifiers();
            String modStr = Modifier.toString(mod);
            if (modStr != null && modStr.length() > 0)
                System.out.print(modStr + " ");

            //打印返回值类型
            Class returnType = method.getReturnType();
            System.out.print(returnType + " ");

            //打印方法名
            System.out.print(method.getName() + "(");

            //打印参数列表
            Class[] params = method.getParameterTypes();
            for(int i=0;i<params.length;++i){
                if(i!=0)
                    System.out.print(", ");
                System.out.print(params[i].getName());
            }
            System.out.print(")");

            //打印异常声明
            Class[] exceptions = method.getExceptionTypes();
            if(exceptions.length>0){
                System.out.print(" throws ");
                for(int i=0;i<exceptions.length;++i){
                    if(i!=0)
                        System.out.print(", ");
                    System.out.print(exceptions[i].getName());
                }
            }

            System.out.println(";");
        }
    }

    //打印构造函数信息
    public static void printConstructor(Class clazz) {
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor:constructors){
            //打印缩进
            System.out.print("\t");

            //打印修饰符
            int mod = constructor.getModifiers();
            String modStr = Modifier.toString(mod);
            if(modStr!=null&&modStr.length()>0)
                System.out.print(modStr + " ");

            //打印构造函数名
            System.out.print(constructor.getName()+"(");

            //打印参数列表
            Class[] params = constructor.getParameterTypes();
            for (int i = 0; i < params.length; ++i) {
                if(i!=0)
                    System.out.print(" ,");
                System.out.print(params[i].getName());
            }

            System.out.println(");");
        }
    }
}
